package com.nervenets.web.controller.building;

import com.nervenets.Global;
import com.nervenets.utils.JodaUtils;
import com.nervenets.utils.PropertiesLoader;
import com.nervenets.utils.StringUtils;
import com.nervenets.web.controller.*;
import com.nervenets.web.entity.KeyValue;
import com.nervenets.web.entity.MessageCode;
import com.nervenets.web.enumeration.CheckStatus;
import com.nervenets.web.hibernate.dao.BuildingDao;
import com.nervenets.web.hibernate.dao.ManagerDao;
import com.nervenets.web.hibernate.dao.PreordainDao;
import com.nervenets.web.hibernate.domain.Building;
import com.nervenets.web.hibernate.domain.Manager;
import com.nervenets.web.hibernate.domain.Preordain;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.persistence.criteria.Predicate;
import javax.validation.ConstraintViolation;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Api(value = "楼盘接口v1", description = "楼盘相关接口")
@RestController
@RequestMapping("/api/v1/building")
public class BuildingController extends BaseController {
    @Resource
    private BuildingDao buildingDao;
    @Resource
    private ManagerDao managerDao;
    @Resource
    private PreordainDao preordainDao;

    @ApiOperation("楼盘列表")
    @PostMapping("/list")
    public String list(@RequestBody BuildingPagingParams params) {
        final Set<ConstraintViolation<BuildingPagingParams>> errors = validator.validate(params);
        if (!errors.isEmpty()) {
            return errorMessage(errors);
        }

        Specification<Building> specification = (Specification<Building>) (root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (null != params.getCheckStatus()) {
                predicates.add(criteriaBuilder.equal(root.get("checkStatus"), params.getCheckStatus()));
            }
            if (params.getManagerId() > 0) {
                predicates.add(criteriaBuilder.equal(root.get("manager").get("id"), params.getManagerId()));
            }
            if (!StringUtils.isEmpty(params.getName())) {
                predicates.add(criteriaBuilder.like(root.get("name"), "%" + params.getName() + "%"));
            }
            switch (params.getSincer()) {
                case 0:
                    break;
                case 1:
                    predicates.add(criteriaBuilder.greaterThan(root.get("sincer"), 0));
                    break;
                case 2:
                    predicates.add(criteriaBuilder.equal(root.get("sincer"), 0));
                    break;
            }
            switch (params.getDating()) {
                case 0:
                    break;
                case 1:
                    predicates.add(criteriaBuilder.isTrue(root.get("dating")));
                    break;
                case 2:
                    predicates.add(criteriaBuilder.isFalse(root.get("dating")));
                    break;
            }
            return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
        };
        final Page<Building> pages = buildingDao.findAll(specification, PageRequest.of(params.getPage(), params.getLimit(), new Sort(Sort.Direction.DESC, "id")));
        List<BuildingListDto> buildings = new ArrayList<>();
        pages.map(building -> buildings.add(new BuildingListDto(building)));

        return successMessage(buildings, new KeyValue("page", params.getPage()), new KeyValue("total", pages.getTotalElements()));
    }

    @ApiOperation("楼盘审核")
    @PostMapping("/check")
    public String check(@RequestBody CheckParams params) throws Exception {
        final Set<ConstraintViolation<CheckParams>> errors = validator.validate(params);
        if (!errors.isEmpty()) {
            return errorMessage(errors);
        }
        return (String) redisSyncLocker.idLock(params.getTargetId(), o -> {
            Building building = buildingDao.findById(params.getTargetId()).orElse(null);
            if (null == building) return errorMessage(MessageCode.code_404);
            building.setCheckStatus(params.getChangeTo());
            building.setRemark(params.getReason());
            buildingDao.save(building);
            return successMessage(building);
        });
    }

    @ApiOperation("楼盘详情")
    @PostMapping("/detail")
    public String detail(@RequestBody DetailParams params) {
        final Set<ConstraintViolation<DetailParams>> errors = validator.validate(params);
        if (!errors.isEmpty()) {
            return errorMessage(errors);
        }

        Building building = null;
        if (params.getTargetId() > 0) {
            building = buildingDao.findById(params.getTargetId()).orElse(null);
            if (null == building) return errorMessage(MessageCode.code_404, "您要查看的楼盘不存在");
        } else {
            final Manager manager = managerDao.findById(params.resolveUserId()).orElse(null);
            if (null == manager) return errorMessage(MessageCode.code_777);
            building = buildingDao.findTop1ByManager(manager);
            if (null == building) return errorMessage(MessageCode.code_404, "您要查看的楼盘不存在");
        }

        return successMessage(building);
    }

    @ApiOperation("楼盘添加或编辑")
    @PostMapping("/edit")
    public String edit(@RequestBody BuildingEditParams params) {
        final Set<ConstraintViolation<BuildingEditParams>> errors = validator.validate(params);
        if (!errors.isEmpty()) {
            return errorMessage(errors);
        }

        final Manager manager = managerDao.findById(params.getManagerId()).orElse(null);
        if (null == manager) return errorMessage(MessageCode.code_404, "您选择的楼盘开发商不存在");

        Building building = new Building();
        if (params.getBuildingId() > 0) {
            building = buildingDao.findById(params.getBuildingId()).orElse(null);
            if (null == building) return errorMessage(MessageCode.code_404, "您编辑的楼盘不存在");
        }

        building.setName(params.getName());
        building.setCover(params.getCover());
        building.setDating(params.isDating());
        building.setSincer(params.getSincer());
        building.setSincerStartTime(params.getSincerStartTime());
        building.setSincerEndTime(params.getSincerEndTime());
        building.setSincerThawTime(params.getSincerThawTime());
        building.setTags(params.getTags());
        building.setDescription(params.getDescription());
        building.setPrice(params.getPrice());
        building.setTotalPrice(params.getTotalPrice());
        building.setArea(params.getArea());
        building.setType(params.getType());
        building.setHouseTypeText(params.getHouseTypeText());
        building.setHouseTypes(params.getHouseTypes());
        building.setStructure(params.getStructure());
        building.setOpenTime(params.getOpenTime());
        building.setAddress(params.getAddress());
        building.setLongitude(params.getLongitude());
        building.setLatitude(params.getLatitude());
        building.setSaleAddress(params.getSaleAddress());
        building.setSaleLongitude(params.getSaleLongitude());
        building.setSaleLatitude(params.getSaleLatitude());
        building.setRightYear(params.getRightYear());
        building.setDecorationStandard(params.getDecorationStandard());
        building.setPropertyCost(params.getPropertyCost());
        building.setPropertyCompany(params.getPropertyCompany());
        building.setOnSale(params.isOnSale());
        building.setManager(manager);
        building.setCheckStatus(CheckStatus.checking);
        buildingDao.save(building);

        globalService.clearRedisBuildingStored(building.getId());
        return successMessage();
    }

    @ApiOperation("更新楼盘相册")
    @PostMapping("/updateAlbums")
    public String updateAlbums(@RequestBody UpdateAlbumsParams params) {
        final Set<ConstraintViolation<UpdateAlbumsParams>> errors = validator.validate(params);
        if (!errors.isEmpty()) {
            return errorMessage(errors);
        }
        Building building = buildingDao.findById(params.getBuildingId()).orElse(null);
        if (null == building) return errorMessage(MessageCode.code_404, "您编辑的楼盘不存在");

        building.setAlbums(params.getAlbums());
        buildingDao.save(building);

        return successMessage(building);
    }

    @ApiOperation("楼盘删除")
    @PostMapping("/del")
    public String del(@RequestBody IdTokenParams params) {
        final Set<ConstraintViolation<IdTokenParams>> errors = validator.validate(params);
        if (!errors.isEmpty()) {
            return errorMessage(errors);
        }

        Building building = buildingDao.findById(params.getTargetId()).orElse(null);
        if (null == building) return errorMessage(MessageCode.code_404, "您要删除的楼盘不存在");

        buildingDao.delete(building);

        return successMessage();
    }

    @ApiOperation("看房预定检查")
    @PostMapping("/preordainCheck")
    public String preordainCheck(@RequestBody IdTokenParams params) {
        if (params.tokenIllegal()) return errorMessage(MessageCode.code_777);
        final Set<ConstraintViolation<IdTokenParams>> errors = validator.validate(params);
        if (!errors.isEmpty()) {
            return errorMessage(errors);
        }
        final Preordain has = preordainDao.findTop1ByBuildingIdAndUserId(params.getTargetId(), params.resolveUserId());
        return successMessage(null != has);
    }

    @ApiOperation("看房预定")
    @PostMapping("/preordain")
    public String preordain(@RequestBody PreordainParams params) {
        if (params.tokenIllegal()) return errorMessage(MessageCode.code_777);
        final Set<ConstraintViolation<PreordainParams>> errors = validator.validate(params);
        if (!errors.isEmpty()) {
            return errorMessage(errors);
        }

        Building building = buildingDao.findById(params.getBuildingId()).orElse(null);
        if (null == building) return errorMessage(MessageCode.code_404, "您选择的楼盘不存在");

        final Preordain has = preordainDao.findTop1ByBuildingIdAndUserId(building.getId(), params.resolveUserId());
        if (null != has) return errorMessage(MessageCode.code_444, "您已经预约过该楼盘，请等待客户经理联系您");

        Preordain preordain = new Preordain();
        preordain.setManagerId(building.getManager().getId());
        preordain.setBuildingId(building.getId());
        preordain.setUserId(params.resolveUserId());
        preordain.setName(params.getName());
        preordain.setGender(params.getGender());
        preordain.setMobile(params.getMobile());
        preordainDao.save(preordain);
        return successMessage();
    }

    @ApiOperation("看房预定列表")
    @PostMapping("/preordains")
    public String preordains(@RequestBody PreordainPagingParams params) {
        final Set<ConstraintViolation<PreordainPagingParams>> errors = validator.validate(params);
        if (!errors.isEmpty()) {
            return errorMessage(errors);
        }

        Specification<Preordain> specification = (Specification<Preordain>) (root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (params.getManagerId() > 0) {
                predicates.add(criteriaBuilder.equal(root.get("managerId"), params.getManagerId()));
            }
            if (params.getBuildingId() > 0) {
                predicates.add(criteriaBuilder.equal(root.get("buildingId"), params.getBuildingId()));
            }
            return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
        };
        final Page<Preordain> pages = preordainDao.findAll(specification, PageRequest.of(params.getPage(), params.getLimit(), new Sort(Sort.Direction.DESC, "id")));

        return successMessage(pages.getContent(), new KeyValue("page", params.getPage()), new KeyValue("total", pages.getTotalElements()));
    }

    @ApiOperation("看房预定标记处理")
    @PostMapping("/preordainHandle")
    public String preordainHandle(@RequestBody IdTokenParams params) {
        final Set<ConstraintViolation<IdTokenParams>> errors = validator.validate(params);
        if (!errors.isEmpty()) {
            return errorMessage(errors);
        }

        final Preordain preordain = preordainDao.findById(params.getTargetId()).orElse(null);
        if (null == preordain) return errorMessage(MessageCode.code_404, "预约信息不存在");
        preordain.setHandleTime(JodaUtils.getTimestamp());
        preordainDao.save(preordain);
        return successMessage();
    }

    @ApiOperation("看房预定数据下载地址")
    @PostMapping("/preordainsDataUrl")
    public String preordainsDataUrl(@RequestBody DataDownloadParams params) throws IOException {
        final Set<ConstraintViolation<DataDownloadParams>> errors = validator.validate(params);
        if (!errors.isEmpty()) {
            return errorMessage(errors);
        }

        final List<Preordain> preordains = preordainDao.findAllByManagerIdAndBuildingId(params.getManagerId(), params.getBuildingId());

        //创建HSSFWorkbook对象(excel的文档对象)
        HSSFWorkbook wb = new HSSFWorkbook();
        //建立新的sheet对象（excel的表单）
        HSSFSheet sheet = wb.createSheet("看房预定数据");

        HSSFRow row2 = sheet.createRow(0);
        row2.createCell(0).setCellValue("提交时间");
        row2.createCell(1).setCellValue("姓名");
        row2.createCell(2).setCellValue("电话");
        row2.createCell(3).setCellValue("预约时间");

        int rowIndex = 1;
        for (Preordain preordain : preordains) {
            HSSFRow dataRow = sheet.createRow(rowIndex++);
            dataRow.createCell(0).setCellValue(JodaUtils.timeLongToString(preordain.getCreateTime() * 1000L));
            dataRow.createCell(1).setCellValue(preordain.getName());
            dataRow.createCell(2).setCellValue(preordain.getMobile());
            dataRow.createCell(3).setCellValue(JodaUtils.timeLongToString(preordain.getCreateTime() * 1000L, "yyyy-MM-dd"));
        }

        final PropertiesLoader propertiesLoader = Global.getApplicationProperties();
        StringBuilder buffer = new StringBuilder();
        buffer.append(propertiesLoader.getProperty("api.upload.folder")).append(File.separatorChar).append("excel").append(File.separatorChar);
        if (!new File(buffer.toString()).exists()) {
            System.out.println("不存在:" + buffer.toString());
            boolean success = new File(buffer.toString()).mkdirs();
            System.out.println("创建文件夹成功没：" + success);
        }
        buffer.append("building_").append(params.getBuildingId()).append(".xls");

        FileOutputStream fout = new FileOutputStream(buffer.toString());
        wb.write(fout);
        fout.close();

        return successMessage("http://" + propertiesLoader.getProperty("api.upload.domain") + "/excel/building_" + params.getBuildingId() + ".xls");
    }
}
